package com.ruoyi.common.core.utils;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.SecureRandom;

/**
 * Author:cgChen
 * Date:2022/05/12 19:47
 * Description: 数据加密、解密
 */
public class EncryptAesUtil {
    private static Logger logger = LoggerFactory.getLogger(EncryptAesUtil.class);
    /**
     * 密钥 AES加解密要求key必须要128个比特位（这里需要长度为16，否则会报错）
     */
    //private static final String KEY = "xxl_job_12345678";
    private static String KEY = "sjmc_app_1234567";

    /**
     * 算法
     */
    private static final String ALGORITHMS = "AES/ECB/PKCS5Padding";
    /**
     * 静态常量
     */
    private static final String AES = "AES";

    //public static void main(String[] args) {
    //    logger.info("加密密钥和解密密钥：{}", KEY);
    //
    //    String content = "SBAZCSJYBAGDYQDF";
    //    logger.info("加密前：" + content);
    //
    //    String encrypt = aesEncrypt(content);
    //    logger.info("加密后：" + encrypt);
    //
    //    String decrypt = aesDecrypt(encrypt);
    //    logger.info("解密后：" + decrypt);
    //}

    /**
     * 加密
     * @param sessionId
     * @param time
     * @param content
     * @return
     */
    public static String encrypt(String sessionId,String time,String content){
        generateKey(sessionId,time);
        String encrypt = encrypt(aesEncrypt(content));
        return encrypt;
    }

    /**
     * 解密
     * @param sessionId
     * @param time
     * @param content
     * @return
     */
    public static String decrypt(String sessionId,String time,String content){
        generateKey(sessionId,time);
        String decrypt = aesDecrypt(decrypt(content));
        return decrypt;
    }

    /**
     * 生成加密、解密秘钥
     * @return
     */
    private static void generateKey(String sessionId,String time){
        KEY=md5(sessionId+time);
    }

    /**
     * MD5加密之方法二
     * @explain java实现
     * @param str
     *            待加密字符串
     * @return 16进制加密字符串
     */
    public static String md5(String str) {
        // 加密后的16进制字符串
        String hexStr = "";
        try {
            // 此 MessageDigest 类为应用程序提供信息摘要算法的功能
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            // 转换为MD5码
            byte[] digest = md5.digest(str.getBytes("utf-8"));
            hexStr = ByteUtils.toHexString(digest);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hexStr;
    }

    /**
     * 将字符串【AES加密】为base 64 code
     *
     * @param content 待加密的内容
     * @return 加密后的base 64 code
     */
    public static String aesEncrypt(String content) {
        try {
            // 创建密码器
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            kgen.init(128);
            // 初始化为加密模式的密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(EncryptAesUtil.KEY.getBytes(), EncryptAesUtil.AES));

            byte[] bytes = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            // 使用base64解码
            return Base64.encodeBase64String(bytes);
        } catch (Exception e) {
            logger.error(e.getMessage() + e);
        }
        return null;
    }

    /**
     * 将base 64 code 【AES解密】为字符串
     *
     * @param encryptStr 待解密的base 64 code
     * @return 解密后的String
     */
    public static String aesDecrypt(String encryptStr) {
        try {
            if (StringUtils.isEmpty(encryptStr)) {
                return null;
            }
            // 将字符串转为byte，返回解码后的byte[]
            byte[] encryptBytes = new BASE64Decoder().decodeBuffer(encryptStr);

            // 创建密码器
            KeyGenerator kgen = KeyGenerator.getInstance(EncryptAesUtil.AES);
            kgen.init(128);
            // 初始化为解密模式的密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(EncryptAesUtil.KEY.getBytes(), EncryptAesUtil.AES));
            byte[] decryptBytes = cipher.doFinal(encryptBytes);

            return new String(decryptBytes);
        } catch (Exception e) {
            logger.error(e.getMessage() + e);
        }
        return null;
    }


    //Des加密、解密

    private final static String DES = "DES";

    /**
     * 根据键值进行加密
     * @param data
     * @return
     */
    public static String encrypt(String data) {
        String key = md5(KEY.substring(KEY.length()-9,KEY.length()));
        byte[] bt = encrypt(data.getBytes(), key.getBytes());
        String strs = new BASE64Encoder().encode(bt);
        return strs;
    }

    /**
     * 根据键值进行解密
     * @param data
     * @return
     */
    public static String decrypt(String data) {
        try {
            String key = md5(KEY.substring(KEY.length()-9,KEY.length()));
            if (data == null)
                return null;
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] buf = decoder.decodeBuffer(data);
            byte[] bt = decrypt(buf, key.getBytes());
            return new String(bt);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *根据键值进行加密
     * @param data
     * @param key  加密键byte数组
     * @return
     */
    private static byte[] encrypt(byte[] data, byte[] key)  {
        try {
            // 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();

            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);

            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);

            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(DES);

            // 用密钥初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);

            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据键值进行解密
     * @param data
     * @param key  加密键byte数组
     * @return
     */
    private static byte[] decrypt(byte[] data, byte[] key)  {
        try {
            // 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();

            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);

            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);

            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance(DES);

            // 用密钥初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, sr);

            return cipher.doFinal(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

